package DRCOMM;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class dr_util {
    
    /**
     * 转换 String[] 为 List<String>
     * @param Strings
     * @return
     */
    public static List<String> StringsToList(String[] Strings){
        List<String> result=new ArrayList<String>();
        for(String s:Strings){
            result.add(s);
        }
        return result;
    }

    /**
     * 转换 List<byte >为 byte[]
     * @param buff
     * @return
     */
    public static byte[] ListToBytes(List<Byte> buff){
        byte[] result=new byte[buff.size()];
        for(int i=0;i<buff.size();i++){
            result[i]=buff.get(i);
        }
        return result;
    }

    /**
     * 转换 List<Integer >为 byte[]
     * @param buff
     * @return
     */
    public static byte[] ListToBytes2(List<Integer> buff){
        byte[] result=new byte[buff.size()];
        for(int i=0;i<buff.size();i++){
            result[i]=(byte)buff.get(i).intValue();
        }
        return result;
    }

    /**
     * 转换 List<byte >为 byte[]
     * @param buff
     * @return
     */
    public static int[] ListToInts(List<Integer> buff){
        int[] result=new int[buff.size()];
        for(int i=0;i<buff.size();i++){
            result[i]=buff.get(i);
        }
        return result;
    }

    /**
     * 转换 byte[] 为 List<byte>
     * @param buff
     * @return
     */
    public static List<Byte> BytesToList(byte[] buff){
        List<Byte> result=new ArrayList<Byte>();
        for(int i=0;i<buff.length;i++){
            result.add(buff[i]);
        }
        return result;
    }

    /**
     * 转换 byte[] 为 List<byte>
     * @param buff
     * @return
     */
    public static List<Byte> BytesToList(byte[] buff,int length){
        List<Byte> result=new ArrayList<Byte>();
        for(int i=0;i<length&&i<buff.length;i++){
            result.add(buff[i]);
        }
        return result;
    }

    /**
     * 转换 int[] 为 List<int>
     * @param buff
     * @return
     */
    public static List<Integer> IntsToList(int[] buff){
        List<Integer> result=new ArrayList<Integer>();
        for(int i=0;i<buff.length;i++){
            result.add(buff[i]);
        }
        return result;
    }

    /**
     * 转换byte字节为16进制对应的文本，主要为写入报文日志，以便于分析日志
     * @param inbytes
     * @param length
     * @return
     */
    public static String bytes2hexstr(byte[] inbytes,int length){
        String result="";
        for(int i=0;i<length;i++){
            result+=String.format("%02X ", inbytes[i]);
        }
        // 去掉最后的空格
        if(result.length()>0)result=result.substring(0, result.length()-1);
        return result;
    }

    /**
     * 转换byte字节为16进制对应的文本，主要为写入报文日志，以便于分析日志
     * @param inbytes
     * @param length
     * @return
     */
    public static String bytes2hexstr(byte[] inbytes){
        String result="";
        for(int i=0;i<inbytes.length;i++){
            result+=String.format("%02X ", inbytes[i]);
        }
        // 去掉最后的空格
        if(result.length()>0)result=result.substring(0, result.length()-1);
        return result;
    }

    /**
     * 转换int[]为字符串
     * 转换为该16进制的字符串表示
     * 如 0xAB,则转换为"AB"
     * 多个数值通过空格间隔
     * @param inbytes
     * @param data_length
     * @return
     */
    public static String ints2hexstr(int[] inbytes){
        String result="";
        for(int i=0;i<inbytes.length;i++){
            result+=String.format("%02X ", inbytes[i]);
        }
        // 去掉最后的空格
        if(result.length()>0)result=result.substring(0, result.length()-1);
        return result;
    }

    /**
     * 转换int[]为字符串
     * 转换为该16进制的字符串表示
     * 如 0xAB,则转换为"AB"
     * 多个数值通过空格间隔
     * @param inbytes
     * @param data_length
     * @return
     */
    public static String ints2hexstr(int[] inbytes,int data_length){
        String result="";
        int value;
        for(int i=0;i<inbytes.length&&i<data_length;i++){
            if(inbytes[i]>0)
                value=inbytes[i];
            else
                value=-inbytes[i];
            result+=String.format("%02X ", value);
        }
        // 去掉最后的空格
        if(result.length()>0)result=result.substring(0, result.length()-1);
        return result;
    }

    /**
     * 转换int[]为byte[]
     * @param data
     * @return
     */
    public static byte[] ints2bytes(int[] data){
        byte[] result=new byte[data.length];
        int value;
        for(int i=0;i<data.length;i++){
            if(data[i]>0)
                value=data[i];
            else
                value=-data[i];
            result[i]=(byte)value;
        }
        return result;
    }

    /**
     * 转换byte[]为int[]
     * @param data
     * @return
     */
    public static int[] bytes2ints(byte[] data){
        int[] result=new int[data.length];
        for(int i=0;i<data.length;i++){
            result[i]=(int)data[i]&0xFF;
        }
        return result;
    }

    /**
     * 转换byte[]为ArrayList<Byte>
     * @param data
     * @return
     */
    public static ArrayList<Byte> convertBytes2ArrayList(byte[] data){
        ArrayList<Byte> result=new ArrayList<Byte>();
        for(int i=0;i<data.length;i++){
            result.add(data[i]);
        }
        return result;
    }

    /**
     * Java 总是把 byte 当做有符号数处理；通过将其和 0xFF 进行二进制与得到它的无符号数
     * @param b
     * @return
     */
    public static int byteToInt(byte b) {
        return b & 0xFF;
    }
    
    /**
     * 根据给出的data字节码，生成md5
     * @param data
     * @return
     */
    public static byte[] md5Digest(byte[] data) {
        // 加密后的16进制字符串
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                data);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有这个md5算法！");
        }
        // String md5code = new BigInteger(1, secretBytes).toString(16);
        // for (int i = 0; i < 32 - md5code.length(); i++) {
        //     md5code = "0" + md5code;
        // }
        // System.out.println(md5code);
        return secretBytes;
    }

    /**
     * 根据给出的data字节码，生成md5
     * @param data
     * @return
     */
    public static byte[] md5Digest(int[] data) {
        // 加密后的16进制字符串
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                dr_util.ints2bytes(data));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有这个md5算法！");
        }
        // String md5code = new BigInteger(1, secretBytes).toString(16);
        // for (int i = 0; i < 32 - md5code.length(); i++) {
        //     md5code = "0" + md5code;
        // }
        // System.out.println(md5code);
        return secretBytes;
    }

    public static int[] md5Digest2ints(byte[] data) {
        // 加密后的16进制字符串
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                data);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有这个md5算法！");
        }
        int[] result=new int[secretBytes.length];
        for(int i=0;i<secretBytes.length;i++){
            result[i]=(int)secretBytes[i]&0xFF;
        }
        return result;
    }

    /**
     * 转换IEEE754的4个字节为float
     * @param data
     * @return
     * @throws Exception
     */
    public static float IEEE_STD_754_to_float(byte[] data) throws Exception{
        float result=0;
        try {
            int value=data[0]*256*256*256+data[1]*256*256+data[2]*256+data[3];
            result=Float.intBitsToFloat(value);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("(DR)IEEE 754 convert error!");
        }
        return result;
    }

    /**
     * 转换IEEE754的4个字节为float
     * @param data
     * @return
     * @throws Exception
     */
    public static float IEEE_STD_754_to_float(int[] data) throws Exception{
        float result=0;
        try {
            int value=data[3]*256*256*256+data[2]*256*256+data[1]*256+data[0];
            result=Float.intBitsToFloat(value);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("(DR)IEEE 754 convert error!");
        }
        return result;
    }

    /**
     * 转换float为IEEE754格式的4个字节
     * @param data
     * @return
     */
    public static int[] float_to_IEEE_STD_754(float data){
        int[] result=new int[4];
        int value=Float.floatToIntBits(data);
        result[3]=(int)((value>>>24)&0xFF); 
        result[2]=(int)((value>>>16)&0xFF); 
        result[1]=(int)((value>>>8)&0xFF); 
        result[0]=(int)(value&0xFF); 
        return result;
    }

    /**
     * 转换float为IEEE754格式的4个字节
     * @param data
     * @return
     */
    public static Integer[] float_to_IEEE_STD_754_Integer(float data){
        Integer[] result=new Integer[4];
        int value=Float.floatToIntBits(data);
        result[3]=(int)((value>>>24)&0xFF); 
        result[2]=(int)((value>>>16)&0xFF); 
        result[1]=(int)((value>>>8)&0xFF); 
        result[0]=(int)(value&0xFF); 
        return result;
    }

    /**合并2个List为1个List
     * @param list1
     * @param list2
     * @return
     */
    public static List<String> List_Add_List(List<String> list1,List<String> list2){
        List<String> result=list1;
        for(String list2_item:list2){
            list1.add(list2_item);
        }
        return result;
    }

    /**
     * 转换2位16进制字符串为整形值
     * @param hexString
     * @return
     * @throws Exception
     */
    public static int HexStr2_to_int(String hexString) throws Exception{
        int result=-1;
        if(hexString.length()!=2) throw new Exception("error,input Hex String must be 2 bytes!");
        hexString = hexString.toUpperCase();
        char[] hexs=hexString.toCharArray();
        String HexDigital="0123456789ABCDEF";
        result=HexDigital.indexOf(hexs[0])*16+HexDigital.indexOf(hexs[1]);
        return result;
    }

    /**
     * 转换2个16进制字符串为整形
     * 如16进制字符串 "12 34"，则返回4660
     * 即0x12=18,0x34=52,18*256+52=4660
     * @param hexString
     * @return
     * @throws Exception
     */
    public static int HexStr2int(String hexString) throws Exception{
        int result=-1;
        String[] subStr=hexString.split(" ");
        try {
            if(subStr.length!=2)throw new Exception("error,input Hex String error!");
            result=HexStr2_to_int(subStr[0])*256+HexStr2_to_int(subStr[1]);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 访问指定URL地址
     * @param inurl:URL地址
     * @return 返回的内容
     */
    public static String open_url(String inurl){
        String result="";
        try {
            URL url=new URL(inurl);
            URLConnection urlConnection;
            try {
                urlConnection = url.openConnection();
                HttpURLConnection connection=null;
                if(urlConnection instanceof HttpURLConnection){
                    connection=(HttpURLConnection)urlConnection;
                    BufferedReader in = new BufferedReader(
                        new InputStreamReader(connection.getInputStream()));
                    String urlString = "";
                    String current;
                    while((current = in.readLine()) != null){
                        urlString += current;
                    }
                    System.out.println(urlString);
                    return urlString;
                }else{
                    System.out.println("conntion url fail!");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        }
        return result;
    }

    /**
     * 转换json字符串为Map<String,Object>
     * @param json
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Map<String,Object> json2Map(String json){
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String,Object> result=null;
            result=objectMapper.readValue(json, HashMap.class);
            return result;
        } catch (JsonParseException e) {
            e.printStackTrace();
            return null;
        } catch (JsonMappingException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 检查远端端口是否可连接
     * 即链路是否正常
     * @param host 主机IP
     * @param port 端口号
     * @return 链路状态
     */
    public static boolean check_link_state(String host,int port){
        boolean result=false;
        try{
            Socket socket=new Socket();
            socket.connect(new InetSocketAddress(host,port),100);
            socket.close();
            return true;
        } catch (Exception e){
            System.out.println(String.format("host:[%s:%d] can't connect!",host,port));
        }
        return result;
    }

    public static String get_now_str(String inTime){
        String now_str;
        SimpleDateFormat ft=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now=new Date();
        if(inTime==null||inTime==""){
            now_str=ft.format(now);
        }else{
            try {
                now = ft.parse(inTime);
                now_str=ft.format(now);
            } catch (ParseException e) {
                now=new Date();
                now_str=ft.format(now);
                e.printStackTrace();
            }
        }
        return now_str;
    }

    /**
     * 获取指定目录下文件
     * includeSub:为真时读取包含子目录文件，否则不读取
     * @param path
     * @param includeSub:为真时读取包含子目录文件，否则不读取
     * @return 文件名列表
     */
    public static List<String> getPathFilenames(String path,Boolean includeSub){
        List<String> filenames=new ArrayList<String>();
        File path_file=new File(path);
        if(path_file.exists()){
            for(File f:path_file.listFiles()){
                if(f.isFile()){
                    filenames.add(f.getName());
                }else{
                    if(includeSub!=null&&includeSub){
                        List<String> subPathFilenames=getPathFilenames(f.getName(), includeSub);
                        for(String spf:subPathFilenames){
                            filenames.add(spf);
                        }
                    }
                }
            }
        }
        return filenames;
    }

    /**
     * 大端模式2字节整数
     * @param data
     * @return
     */
    public static int byte2toshort_b(byte[] data){
        int result=-1;
        int dl=data[1]&0xFF;//低位
        int dh=data[0]&0xFF;//高位
        result=(short)(dh<<8|dl);
        return result;
    }

    /**
     * 小端模式2字节整数
     * @param data
     * @return
     */
    public static int byte2toshort_s(byte[] data){
        int result=-1;
        int dl=data[0]&0xFF;//低位
        int dh=data[1]&0xFF;//高位
        result=(short)(dh<<8|dl);
        return result;
    }

    /**
     * 大端模式4字节IEEE 754浮点数
     * @param data
     * @return
     */
    public static float byte4tofloat_b(byte[] data){
        float result=-1;
        // int b1,b2;
        // b1=byte2toshort_b(Arrays.copyOf(data, 2));
        // b2=byte2toshort_b(Arrays.copyOfRange(data, 2, 4));
        // result=dr_util.convert_modbus_int2float32(b1, b2);      
        int[] d=new int[4];
        d[1]=data[0]&0xFF;
        d[0]=data[1]&0xFF;
        d[3]=data[2]&0xFF;
        d[2]=data[3]&0xFF;
        try {
            result=dr_util.IEEE_STD_754_to_float(d); 
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 大端模式4字节IEEE 754浮点数-2-寄存器也大端
     * @param data
     * @return
     */
    public static float byte4tofloat_b2(byte[] data){
        float result=-1;
        // int b1,b2;
        // b1=byte2toshort_b(Arrays.copyOf(data, 2));
        // b2=byte2toshort_b(Arrays.copyOfRange(data, 2, 4));
        // result=dr_util.convert_modbus_int2float32(b1, b2);      
        int[] d=new int[4];
        d[1]=data[2]&0xFF;
        d[0]=data[3]&0xFF;
        d[3]=data[0]&0xFF;
        d[2]=data[1]&0xFF;
        try {
            result=dr_util.IEEE_STD_754_to_float(d); 
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 小端模式4字节IEEE 754浮点数
     * @param data
     * @return
     */
    public static float byte4tofloat_s(byte[] data){
        float result=-1;
        // int b1,b2;
        // b1=byte2toshort_b(Arrays.copyOf(data, 2));
        // b2=byte2toshort_b(Arrays.copyOfRange(data, 2, 4));
        // result=dr_util.convert_modbus_int2float32(b1, b2);      
        int[] d=new int[4];
        d[0]=data[0]&0xFF;
        d[1]=data[1]&0xFF;
        d[2]=data[2]&0xFF;
        d[3]=data[3]&0xFF;
        try {
            result=dr_util.IEEE_STD_754_to_float(d); 
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 小端模式4字节IEEE 754浮点数-2-寄存器也小端
     * @param data
     * @return
     */
    public static float byte4tofloat_s2(byte[] data){
        float result=-1;
        // int b1,b2;
        // b1=byte2toshort_b(Arrays.copyOf(data, 2));
        // b2=byte2toshort_b(Arrays.copyOfRange(data, 2, 4));
        // result=dr_util.convert_modbus_int2float32(b1, b2);      
        int[] d=new int[4];
        d[0]=data[2]&0xFF;
        d[1]=data[3]&0xFF;
        d[2]=data[0]&0xFF;
        d[3]=data[1]&0xFF;
        try {
            result=dr_util.IEEE_STD_754_to_float(d); 
        } catch (Exception e) {
        }
        return result;
    }

    // 转换2个寄存器值为float32值
    public static float convert_modbus_int2float32(int byte1,int byte2){
        int b1=byte1,b2=byte2;
        if(b1<0){
            b1+=65536;
        }
        int sign=b2>>15;
        int exponent=((b2&0x7fff)>>>7)-127;
        int fraction=((b2&0x007f)<<16)+b1;
        float result;
        try {
            result=(float) (Math.pow(-1,sign)*Math.pow(2,exponent)*(1+fraction/Math.pow(2,23))); 
        } catch (Exception e) {
            result=0;
            throw new Error("处理MODBUS 4字节整形数到浮点数错误！");
        }
        return result;
    }

    /**
     * 扫描目录文件
     * 返回为ArrayList的文件列表
     * @param path
     * @return
     */
    public static ArrayList<File> scanLocalPath(String path){
        File dir=new File(path);
        File[] filesAndDirectories=dir.listFiles();
        ArrayList<File> files=new ArrayList<File>();
        for(File fileOrDir:filesAndDirectories){
            if(fileOrDir.isFile()){
                files.add(fileOrDir);
            }
        }
        return files;
    }

    public static boolean moveFile(String srcPath, String destPath){
        File srcFile=new File(srcPath);
        File destFile=new File(destPath);
        if(srcFile.exists()&&srcFile.isFile()){
            if(destFile.exists()&&destFile.isFile()){
                destFile.delete();
            }
            return srcFile.renameTo(destFile);
        }
        return false;
    }

    /**
     * 二进制文件写入
     * @param filename  文件名
     * @param content   文件内容
     */
    public static void binaryFileWriter(String filename,byte[] content){
        try {
            FileOutputStream fos = new FileOutputStream(filename);
            // 创建DataOutputStream对象，将其与FileOutputStream对象相连
            DataOutputStream dos = new DataOutputStream(fos);
            dos.write(content);
            dos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 二进制文件写入
     * @param filename  文件名
     * @param content   文件内容
     */
    public static void binaryFileWriter(String filename,List<Byte> content){
        try {
            File file = new File(filename);
            if(file.exists())file.delete();
            FileOutputStream fos = new FileOutputStream(filename);
            // 创建DataOutputStream对象，将其与FileOutputStream对象相连
            DataOutputStream dos = new DataOutputStream(fos);
            dos.write(dr_util.ListToBytes(content));
            dos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 二进制文件写入
     * @param filename  文件名
     * @param content   文件内容
     */
    public static void binaryFileWriter2(String filename,List<Integer> content){
        try {
            File file = new File(filename);
            if(file.exists())file.delete();
            FileOutputStream fos = new FileOutputStream(filename);
            // 创建DataOutputStream对象，将其与FileOutputStream对象相连
            DataOutputStream dos = new DataOutputStream(fos);
            dos.write(dr_util.ListToBytes2(content));
            dos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        // int[] data={0xc1,0xc9,0x00,0x00};
        // try {
        //     float value=dr_util.IEEE_STD_754_to_float(data);
        //     System.out.println(String.format("%f", value));
        //     System.out.println(dr_util.ints2hexstr(dr_util.float_to_IEEE_STD_754((float) -25.125)));
        // } catch (Exception e) {
        //     e.printStackTrace();
        // }
        // try {
        //     System.out.println(dr_util.HexStr2int("B5 95"));
        // } catch (Exception e) {
        //     e.printStackTrace();
        // }
        // String content=open_url("https://iot.chinadre.com/Version/distribute_version?type=farm&sn=1");
        // System.out.println(content);
        // Map<String,Object> result=json2Map(content);
        // System.out.println(result.get("code"));
        // List<String> filenames=dr_util.getPathFilenames("./", true);
        // for(String filename:filenames){
        //     System.out.println(filename);
        // }
        float i=(float)178.125;
        System.out.println(ints2hexstr(float_to_IEEE_STD_754(i)));
        // byte[] data={0x20,0x00,0x43,0x32};
        // byte[] data={0x43,(byte)0x84,(byte) 0x99,(byte)0x9A};
        byte[] data={0x42,(byte)0x44,(byte) 0x00,(byte)0x00};
        System.out.println(byte4tofloat_b2(data));
    }

}
